package cn.fudan.pms.service.impl;

import cn.fudan.pms.dao.JobDao;
import cn.fudan.pms.domain.bo.*;
import cn.fudan.pms.domain.cont.JobStatus;
import cn.fudan.pms.domain.po.*;
import cn.fudan.pms.mbg.mapper.JobMapper;
import cn.fudan.pms.mbg.mapper.JobRecordMapper;
import cn.fudan.pms.mbg.mapper.OperatorMapper;
import cn.fudan.pms.mbg.mapper.SubJobMapper;
import cn.fudan.pms.service.JobService;
import cn.fudan.pms.util.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class JobServiceImpl implements JobService {
    @Autowired
    private OperatorMapper operatorMapper;
    @Autowired
    private SubJobMapper subJobMapper;
    @Autowired
    private JobMapper jobMapper;
    @Autowired
    private JobRecordMapper jobRecordMapper;
    @Autowired
    private JobDao jobDao;

    @Override
    public String addNewJob(String title, String description, String residentUuid, String platform, String reporterUuid) {
        Job job = new Job();
        job.setUuid(UUIDUtil.generateUUID(title));
        job.setTitle(title);
        job.setDescription(description);
        job.setResidentUuid(residentUuid);
        job.setPlatform(platform);
        job.setStatus(JobStatus.READY.getStatus());
        job.setIssueTime(new Date());
        jobMapper.insert(job);
        // 同步新增子工单
        SubJob subJob = new SubJob();
        subJob.setUuid(UUIDUtil.generateUUID(title));
        subJob.setTitle(title);
        subJob.setDescription(description);
        subJob.setReporterUuid(reporterUuid);
        subJob.setStartTime(new Date());
        subJob.setStatus("open");
        subJob.setJobUuid(job.getUuid());
        subJobMapper.insert(subJob);
        return job.getUuid();
    }


    @Override
    public String assignJob(String jobUuid, String subUuid, String reporterUuid, String title, String description, Equipment equipment) {
        String operatorUuid = selectIdleOperator(equipment.getType());
        SubJob subJob;
        if (subUuid == null) {
            subJob = new SubJob();
            subJob.setUuid(UUIDUtil.generateUUID(title));
            subJob.setStatus("open");
            subJob.setJobUuid(jobUuid);
            subJob.setStartTime(new Date());
            subJobMapper.insert(subJob);
            subUuid = subJob.getUuid();
            // 重新分配时更新已有子工单状态
            JobBO jobBO = jobDao.getJobByUuid(jobUuid);
            List<SubJobBO> subJobBOList = jobBO.getSubJobBOS();
            for (SubJobBO subJobBO : subJobBOList) {
                if (subJobBO.getStatus().equals("open")) {
                    SubJobExample subJobExample = new SubJobExample();
                    subJobExample.createCriteria().andUuidEqualTo(subJobBO.getUuid());
                    SubJob subJob1 = subJobMapper.selectByExample(subJobExample).get(0);
                    subJob1.setStatus("close");
                    subJob1.setEndTime(new Date());
                    subJobMapper.updateByExampleSelective(subJob1, subJobExample);
                    updateOperatorStatus(subJob1.getOperatorUuid(), false);
                }
            }
        } else {
            SubJobExample subJobExample = new SubJobExample();
            subJobExample.createCriteria().andUuidEqualTo(subUuid);
            subJob = subJobMapper.selectByExample(subJobExample).get(0);
        }
        subJob.setTitle(title);
        subJob.setDescription(description);
        subJob.setOperatorUuid(operatorUuid);
        subJob.setReporterUuid(reporterUuid);
        subJob.setEquipmentId(equipment.getId());
        subJob.setStartTime(new Date());

        SubJobExample subJobExample = new SubJobExample();
        subJobExample.createCriteria().andUuidEqualTo(subUuid);
        subJobMapper.updateByExampleSelective(subJob, subJobExample);
        // 更新维修工状态
        updateOperatorStatus(operatorUuid, true);
        // 更新报修状态
        JobExample jobExample = new JobExample();
        jobExample.createCriteria().andUuidEqualTo(jobUuid);
        Job job = new Job();
        job.setStatus(JobStatus.REPAIR.getStatus());
        jobMapper.updateByExampleSelective(job, jobExample);
        return operatorUuid;
    }

    @Override
    public String reAssignJob(String jobUuid, String reporterUuid, String title, String description, Equipment equipment) {
        return assignJob(jobUuid, null, reporterUuid, title, description, equipment);
    }

    private String selectIdleOperator(String field) {
        OperatorExample example = new OperatorExample();
        example.createCriteria().andBusyEqualTo(false);
        List<Operator> selected = operatorMapper.selectByExample(example).stream()
                .filter(operator -> Arrays.stream(operator.getFields().split(","))
                        .collect(Collectors.toList()).contains(field))
                .collect(Collectors.toList());
        if (selected.isEmpty()) {
            return null;
        }
        return selected.get(0).getUuid();
    }


    @Override
    public String addRecord(String jobUuid, String subUuid, Date startTime, Date endTime, String content) {
        JobBO jobBO = jobDao.getJobByUuid(jobUuid);
        SubJobBO subJobBO = jobBO.getSubJob(subUuid);
        JobRecord record = new JobRecord();
        record.setUuid(UUIDUtil.generateUUID(jobUuid + subUuid));
        record.setOperatorUuid(subJobBO.getOperatorUuid());
        record.setStartTime(startTime);
        record.setEndTime(endTime);
        record.setContent(content);
        record.setSubJobUuid(subUuid);
        subJobBO.addRecord(record);
        jobRecordMapper.insert(record);
        return record.getUuid();
    }

    @Override
    public void done(String jobUuid, String subUuid) {
        // 更新子工单维修状态
        SubJobExample subJobExample = new SubJobExample();
        subJobExample.createCriteria().andUuidEqualTo(subUuid);
        SubJob subJob = subJobMapper.selectByExample(subJobExample).get(0);
        subJob.setStatus("close");
        subJob.setEndTime(new Date());
        subJobMapper.updateByExampleSelective(subJob, subJobExample);
        // 更新报修进度
        JobExample jobExample = new JobExample();
        jobExample.createCriteria().andUuidEqualTo(jobUuid);
        Job job = new Job();
        job.setStatus(JobStatus.DONE.getStatus());
        job.setCloseTime(new Date());
        jobMapper.updateByExampleSelective(job, jobExample);
        updateOperatorStatus(subJob.getOperatorUuid(), false);
    }

    private void updateOperatorStatus(String operatorUuid, Boolean busy) {
        if (operatorUuid == null) return;
        OperatorExample example = new OperatorExample();
        example.createCriteria().andUuidEqualTo(operatorUuid);
        Operator operator = new Operator();
        operator.setBusy(busy);
        operatorMapper.updateByExampleSelective(operator, example);
    }
}
